/**
 * @file menu.h
 * @author eseaoptics.com
 * @brief 串口菜单
 * @note 须配合对应版本的menu_builder使用
 * @version 1.0
 * @date 2023-01-04
 * 
 * @copyright ESEA (c) 2020
 * 
 */
#ifndef MENU_H_
#define MENU_H_
#include <stdint.h>
#include <stddef.h>
#include "menu_config.h"
#include "menu_convert.h"

#ifndef MENU_ECHO       //< 回显开关 当为1时,在菜单使能的情况下会将用户输入的信息发送回去
#define MENU_ECHO (1)
#endif
#ifndef MENU_TERMINAL_WIDTH //< 默认的菜单终端宽度
#define MENU_TERMINAL_WIDTH (80)
#endif
#ifndef MENU_CHINESE_CHARACTER_WIDTH    //< 中文字符的宽度
#define MENU_CHINESE_CHARACTER_WIDTH (2)
#endif
#ifndef MENU_FILL_CHARACTER     //< 菜单填充字符
#define MENU_FILL_CHARACTER ('=')
#endif
#ifndef MENU_INPUT_BUF_SIZE         //< 输入缓冲区大小
#define MENU_INPUT_BUF_SIZE (256)
#else
#if MENU_INPUT_BUF_SIZE>256
#error "\'MENU_INPUT_BUF_SIZE\'最大为256Byte"
#endif
#endif
#ifndef MENU_OUTPUT_BUF_SIZE        //< 输出缓冲区大小
#define MENU_OUTPUT_BUF_SIZE ((MENU_TERMINAL_WIDTH)*3)
#endif

struct menu;
typedef int (*menu_output_function_type)(char *buf,uint32_t size);               //< 发送函数指针类型
typedef int (*menu_check_passwd_function_type)(struct menu *menu,char *passwd,uint32_t size);   //< 密码检查函数指针类型
// typedef int (*menu_save_func_type)(struct menu *menu,struct config cfg);   //< 菜单数据保存到硬件

enum menu_data_type{            //< 菜单数据类型
    MENU_DATA_TYPE_CHAR,        //< 字符型
    MENU_DATA_TYPE_RO_CHAR,     //< 字符型 只读
    MENU_DATA_TYPE_UINT8,       //< 8bit无符号整数
    MENU_DATA_TYPE_RO_UINT8,    //< 8bit无符号整数 只读
    MENU_DATA_TYPE_INT8,        //< 8bit有符号整数
    MENU_DATA_TYPE_RO_INT8,     //< 8bit有符号整数 只读
    MENU_DATA_TYPE_UINT16,      //< 16bit无符号整数
    MENU_DATA_TYPE_RO_UINT16,   //< 16bit无符号整数 只读
    MENU_DATA_TYPE_INT16,       //< 16bit有符号整数
    MENU_DATA_TYPE_RO_INT16,    //< 16bit有符号整数 只读
    MENU_DATA_TYPE_UINT32,      //< 32bit无符号整数
    MENU_DATA_TYPE_RO_UINT32,   //< 32bit无符号整数 只读
    MENU_DATA_TYPE_INT32,       //< 32bit有符号整数
    MENU_DATA_TYPE_RO_INT32,    //< 32bit有符号整数 只读
    MENU_DATA_TYPE_IPV4,        //< ipv4 以32bit无符号整数形式存储
    MENU_DATA_TYPE_RO_IPV4      //< ipv4 以32bit无符号整数形式存储 只读
};
struct menu_tree_node                   //< 菜单树节点
{
    enum menu_data_type data_type;      //< 数据类型
    uint32_t max_value;                 //< 允许的最大值
    uint32_t min_value;                 //< 允许的最小值
    uint16_t next;                      //< 下一个节点， 平行的
    uint16_t child;                     //< 子节点  序号
    uint16_t father;                    //< 父节点
    uint16_t num;                       //< 数据数量
    char *info_str;                     //< 信息
    void *data;                         //< 数据指针
};

struct menu                                         //< 菜单
{
    const struct menu_tree_node *menu_tree;         //< 菜单树
    // void *send_class;                               //< send函数的第一个参数
    menu_output_function_type output;                   //< output 函数   
    // menu_save_func_type menu_save;                  //< save  menu data
    menu_check_passwd_function_type check_passwd;   //< 密码检查函数
    uint16_t node;                                  //< 当前节点  是否显示
    uint16_t child_node;                            //< 当前子节点   当前菜单的子菜单选中节点
    uint8_t child_con;                              //< 子节点计数
    uint8_t input_con;                              //< 输入字符计数
    uint8_t terminal_width;                         //< 终端宽度
    uint8_t flag_ready;                             //< 用户输入完成标志
    uint8_t flag_flush;                             //< 菜单刷新标志
    char input_buf[MENU_INPUT_BUF_SIZE];            //< 用户输入缓冲区
    char output_buf[MENU_OUTPUT_BUF_SIZE];          //< 输出缓冲区
};

struct menu *menu_init(struct menu *menu,const struct menu_tree_node *menu_tree,void *send_class,menu_output_function_type send);
int menu_set_terminal_width(struct menu *menu,uint8_t terminal_width);
int menu_output(struct menu *menu,char *buf,uint32_t size);
int menu_set_hook_passwd(struct menu *menu,menu_check_passwd_function_type check_passwd);
int menu_get_state(struct menu *menu);
void menu_print_callback(struct menu *menu);
void menu_parse_callback(struct menu *menu,char *buf,uint32_t size);
void menu_exit(struct menu *menu) ;
#endif


// /**
//  * @file menu.h
//  * @author Chen Jihang (embedded@eseaoptics.com)
//  * @brief 串口菜单
//  * @note 须配合对应版本的menu_builder使用
//  * @version 1.0
//  * @date 2023-01-04
//  * 
//  * @copyright ESEA (c) 2020
//  * 
//  */
// #ifndef MENU_H_
// #define MENU_H_
// #include <stdint.h>
// #include <stddef.h>
// #include "config.h"
// #include "main.h"

// #ifndef MENU_ECHO       //< 回显开关 当为1时,在菜单使能的情况下会将用户输入的信息发送回去
// #define MENU_ECHO (1)
// #endif
// #ifndef MENU_TERMINAL_WIDTH //< 默认的菜单终端宽度
// #define MENU_TERMINAL_WIDTH (80)
// #endif
// #ifndef MENU_CHINESE_CHARACTER_WIDTH    //< 中文字符的宽度
// #define MENU_CHINESE_CHARACTER_WIDTH (2)
// #endif
// #ifndef MENU_FILL_CHARACTER     //< 菜单填充字符
// #define MENU_FILL_CHARACTER ('=')
// #endif
// #ifndef MENU_INPUT_BUF_SIZE         //< 输入缓冲区大小
// #define MENU_INPUT_BUF_SIZE (256)
// #else
// #if MENU_INPUT_BUF_SIZE>256
// #error "\'MENU_INPUT_BUF_SIZE\'最大为256Byte"
// #endif
// #endif
// #ifndef MENU_OUTPUT_BUF_SIZE        //< 输出缓冲区大小
// #define MENU_OUTPUT_BUF_SIZE ((MENU_TERMINAL_WIDTH)*3)
// #endif
// struct menu;
// typedef int (*menu_output_function_type)(void *send_class,char *buf,uint32_t size);               //< 发送函数指针类型
// typedef int (*menu_check_passwd_function_type)(struct menu *menu,char *passwd,uint32_t size);   //< 密码检查函数指针类型
// enum menu_data_type{            //< 菜单数据类型
//     MENU_DATA_TYPE_CHAR,        //< 字符型
//     MENU_DATA_TYPE_RO_CHAR,     //< 字符型 只读
//     MENU_DATA_TYPE_UINT8,       //< 8bit无符号整数
//     MENU_DATA_TYPE_RO_UINT8,    //< 8bit无符号整数 只读
//     MENU_DATA_TYPE_INT8,        //< 8bit有符号整数
//     MENU_DATA_TYPE_RO_INT8,     //< 8bit有符号整数 只读
//     MENU_DATA_TYPE_UINT16,      //< 16bit无符号整数
//     MENU_DATA_TYPE_RO_UINT16,   //< 16bit无符号整数 只读
//     MENU_DATA_TYPE_INT16,       //< 16bit有符号整数
//     MENU_DATA_TYPE_RO_INT16,    //< 16bit有符号整数 只读
//     MENU_DATA_TYPE_UINT32,      //< 32bit无符号整数
//     MENU_DATA_TYPE_RO_UINT32,   //< 32bit无符号整数 只读
//     MENU_DATA_TYPE_INT32,       //< 32bit有符号整数
//     MENU_DATA_TYPE_RO_INT32,    //< 32bit有符号整数 只读
//     MENU_DATA_TYPE_IPV4,        //< ipv4 以32bit无符号整数形式存储
//     MENU_DATA_TYPE_RO_IPV4      //< ipv4 以32bit无符号整数形式存储 只读
// };
// struct menu_tree_node                   //< 菜单树节点
// {
//     enum menu_data_type data_type;      //< 数据类型
//     uint32_t max_value;                 //< 允许的最大值
//     uint32_t min_value;                 //< 允许的最小值
//     uint16_t next;                      //< 下一个节点
//     uint16_t child;                     //< 子节点
//     uint16_t father;                    //< 父节点
//     uint16_t num;                       //< 数据数量
//     char *info_str;                     //< 信息
//     void *data;                         //< 数据指针
// };
// struct menu                                         //< 菜单
// {
//     const struct menu_tree_node *menu_tree;         //< 菜单树
//     void *send_class;                               //< send函数的第一个参数
//     menu_output_function_type send;                   //< send函数
//     menu_check_passwd_function_type check_passwd;   //< 密码检查函数
//     uint16_t node;                                  //< 当前节点
//     uint16_t child_node;                            //< 当前子节点
//     uint8_t child_con;                              //< 子节点计数
//     uint8_t input_con;                              //< 输入字符计数
//     uint8_t terminal_width;                         //< 终端宽度
//     uint8_t flag_ready;                             //< 用户输入完成标志
//     uint8_t flag_flush;                             //< 菜单刷新标志
//     char input_buf[MENU_INPUT_BUF_SIZE];            //< 用户输入缓冲区
//     char output_buf[MENU_OUTPUT_BUF_SIZE];          //< 输出缓冲区
// };
// // struct menu *menu_init(struct menu *menu,const struct menu_tree_node *menu_tree,void *send_class,menu_output_function_type send);
// struct menu *menu_init(struct menu *menu,const struct menu_tree_node *menu_tree );
// int menu_set_terminal_width(struct menu *menu,uint8_t terminal_width);
// int menu_output(struct menu *menu,char *buf,uint32_t size);
// int menu_set_hook_passwd(struct menu *menu,menu_check_passwd_function_type check_passwd);
// int menu_get_state(struct menu *menu);
// void menu_print_callback(struct menu *menu);
// void menu_parse_callback(struct menu *menu,char *buf,uint32_t size);
// #endif